﻿using System;
using System.Collections;
using System.Collections.Generic;
using GeoAPI.Geometries;

namespace NetTopologySuite.Geometries
{
	public class GeometryCollectionEnumerator : IEnumerator<IGeometry>, IDisposable, IEnumerator, IEnumerable<IGeometry>, IEnumerable
	{
		public GeometryCollectionEnumerator(IGeometry parent)
		{
			this._parent = parent;
			this._atStart = true;
			this._index = 0;
			this._max = parent.NumGeometries;
		}

		public bool MoveNext()
		{
			if (this._atStart)
			{
				return true;
			}
			if (this._subcollectionEnumerator != null)
			{
				if (this._subcollectionEnumerator.MoveNext())
				{
					return true;
				}
				this._subcollectionEnumerator = null;
			}
			return this._index < this._max;
		}

		object IEnumerator.Current
		{
			get
			{
				return this.Current;
			}
		}

		public void Reset()
		{
			this._atStart = true;
			this._index = 0;
		}

		public IGeometry Current
		{
			get
			{
				if (this._atStart)
				{
					this._atStart = false;
					if (GeometryCollectionEnumerator.IsAtomic(this._parent))
					{
						this._index++;
					}
					return this._parent;
				}
				if (this._subcollectionEnumerator != null)
				{
					if (this._subcollectionEnumerator.MoveNext())
					{
						return this._subcollectionEnumerator.Current;
					}
					this._subcollectionEnumerator = null;
				}
				if (this._index >= this._max)
				{
					throw new ArgumentOutOfRangeException();
				}
				IGeometry parent = this._parent;
				int index = this._index;
				this._index = index + 1;
				IGeometry geometryN = parent.GetGeometryN(index);
				if (geometryN is IGeometryCollection)
				{
					this._subcollectionEnumerator = new GeometryCollectionEnumerator((IGeometryCollection)geometryN);
					return this._subcollectionEnumerator.Current;
				}
				return geometryN;
			}
		}

		private static bool IsAtomic(IGeometry geom)
		{
			return !(geom is GeometryCollection);
		}

		public void Dispose()
		{
			if (this._subcollectionEnumerator != null)
			{
				this._subcollectionEnumerator.Dispose();
			}
		}

		public IEnumerator<IGeometry> GetEnumerator()
		{
			return this;
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		private readonly IGeometry _parent;

		private bool _atStart;

		private readonly int _max;

		private int _index;

		private GeometryCollectionEnumerator _subcollectionEnumerator;
	}
}
